From aa24d38a469b59abf1b95b732b6ea9ed86e511cf Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 1 Sep 2005 15:31:12 +0000 Subject: [PATCH] Better Xen backtraces in debug builds (follow the stack frame pointer). Signed-off-by: Keir Fraser --- xen/Rules.mk | 1 - xen/arch/x86/Rules.mk | 4 +- xen/arch/x86/boot/x86_32.S | 5 +- xen/arch/x86/boot/x86_64.S | 4 +- xen/arch/x86/traps.c | 98 +++++++++++++++++++++----- xen/arch/x86/x86_32/traps.c | 7 +- xen/arch/x86/x86_64/traps.c | 5 +- xen/include/asm-x86/processor.h | 4 +- xen/include/asm-x86/x86_32/asm_defns.h | 10 +++ xen/include/asm-x86/x86_64/asm_defns.h | 10 +++ 10 files changed, 111 insertions(+), 37 deletions(-) diff --git a/xen/Rules.mk b/xen/Rules.mk index 511184b08e..4c3cb8db4e 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -7,7 +7,6 @@ debug ?= n perfc ?= n perfc_arrays?= n trace ?= n -optimize ?= y domu_debug ?= n crash_debug ?= n diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 0675d763cd..e73be57bbc 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -13,10 +13,8 @@ CFLAGS += -I$(BASEDIR)/include CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default -ifeq ($(optimize),y) +ifneq ($(debug),y) CFLAGS += -O3 -fomit-frame-pointer -else -x86_32/usercopy.o: CFLAGS += -O1 endif # Prevent floating-point variables from creeping into Xen. diff --git a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S index fafc707bea..ca0c43555a 100644 --- a/xen/arch/x86/boot/x86_32.S +++ b/xen/arch/x86/boot/x86_32.S @@ -9,6 +9,8 @@ .text ENTRY(start) +ENTRY(stext) +ENTRY(_stext) jmp __start .align 4 @@ -260,6 +262,3 @@ ENTRY(idle_pg_table_l2) # Initial page directory is 4kB .org 0x2000 + STACK_SIZE + PAGE_SIZE #endif /* CONFIG_X86_PAE */ - -ENTRY(stext) -ENTRY(_stext) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 85c599f536..fbe5311124 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -10,6 +10,8 @@ .code32 ENTRY(start) +ENTRY(stext) +ENTRY(_stext) jmp __start .org 0x004 @@ -267,5 +269,3 @@ ENTRY(idle_pg_table_l2) .org 0x4000 + STACK_SIZE + PAGE_SIZE .code64 -ENTRY(stext) -ENTRY(_stext) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 107485a5d9..865204a72d 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -100,7 +100,14 @@ unsigned long do_get_debugreg(int reg); static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); -#define stack_words_per_line (32 / BYTES_PER_LONG) + +#ifdef CONFIG_X86_32 +#define stack_words_per_line 8 +#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp) +#else +#define stack_words_per_line 4 +#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp) +#endif int is_kernel_text(unsigned long addr) { @@ -118,17 +125,16 @@ unsigned long kernel_text_end(void) return (unsigned long) &_etext; } -void show_guest_stack(void) +static void show_guest_stack(struct cpu_user_regs *regs) { int i; - struct cpu_user_regs *regs = guest_cpu_user_regs(); unsigned long *stack = (unsigned long *)regs->esp, addr; printk("Guest stack trace from "__OP"sp=%p:\n ", stack); for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { - if ( ((long)stack & (STACK_SIZE-1)) == 0 ) + if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 ) break; if ( get_user(addr, stack) ) { @@ -148,38 +154,98 @@ void show_guest_stack(void) printk("\n"); } -void show_trace(unsigned long *esp) +#ifdef NDEBUG + +static void show_trace(struct cpu_user_regs *regs) { - unsigned long *stack = esp, addr; - int i = 0; + unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; - printk("Xen call trace from "__OP"sp=%p:\n ", stack); + printk("Xen call trace:\n "); - while ( ((long) stack & (STACK_SIZE-1)) != 0 ) + printk("[<%p>]", _p(regs->eip)); + print_symbol(" %s\n ", regs->eip); + + while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 ) { addr = *stack++; if ( is_kernel_text(addr) ) { printk("[<%p>]", _p(addr)); print_symbol(" %s\n ", addr); - i++; } } - if ( i == 0 ) - printk("Trace empty."); + + printk("\n"); +} + +#else + +static void show_trace(struct cpu_user_regs *regs) +{ + unsigned long *frame, next, addr, low, high; + + printk("Xen call trace:\n "); + + printk("[<%p>]", _p(regs->eip)); + print_symbol(" %s\n ", regs->eip); + + /* Bounds for range of valid frame pointer. */ + low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2); + high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info)); + + /* The initial frame pointer. */ + next = regs->ebp; + + for ( ; ; ) + { + /* Valid frame pointer? */ + if ( (next < low) || (next > high) ) + { + /* + * Exception stack frames have a different layout, denoted by an + * inverted frame pointer. + */ + next = ~next; + if ( (next < low) || (next > high) ) + break; + frame = (unsigned long *)next; + next = frame[0]; + addr = frame[(offsetof(struct cpu_user_regs, eip) - + offsetof(struct cpu_user_regs, ebp)) + / BYTES_PER_LONG]; + } + else + { + /* Ordinary stack frame. */ + frame = (unsigned long *)next; + next = frame[0]; + addr = frame[1]; + } + + printk("[<%p>]", _p(addr)); + print_symbol(" %s\n ", addr); + + low = (unsigned long)&frame[2]; + } + printk("\n"); } -void show_stack(unsigned long *esp) +#endif + +void show_stack(struct cpu_user_regs *regs) { - unsigned long *stack = esp, addr; + unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; int i; + if ( GUEST_MODE(regs) ) + return show_guest_stack(regs); + printk("Xen stack trace from "__OP"sp=%p:\n ", stack); for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { - if ( ((long)stack & (STACK_SIZE-1)) == 0 ) + if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 ) break; if ( (i != 0) && ((i % stack_words_per_line) == 0) ) printk("\n "); @@ -190,7 +256,7 @@ void show_stack(unsigned long *esp) printk("Stack empty."); printk("\n"); - show_trace(esp); + show_trace(regs); } /* diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 34c7871a2c..091b4e11de 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -79,11 +79,8 @@ void show_registers(struct cpu_user_regs *regs) "ss: %04lx cs: %04lx\n", ds, es, fs, gs, ss, cs); - if ( GUEST_MODE(regs) ) - show_guest_stack(); - else - show_stack((unsigned long *)®s->esp); -} + show_stack(regs); +} void show_page_walk(unsigned long addr) { diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 5e9701a1f6..7fee601699 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -32,10 +32,7 @@ void show_registers(struct cpu_user_regs *regs) regs->r12, regs->r13, regs->r14); printk("r15: %016lx\n", regs->r15); - if ( GUEST_MODE(regs) ) - show_guest_stack(); - else - show_stack((unsigned long *)regs->rsp); + show_stack(regs); } void show_page_walk(unsigned long addr) diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 82b8cbce62..b312175e8c 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -496,9 +496,7 @@ extern inline void prefetchw(const void *x) #endif -void show_guest_stack(); -void show_trace(unsigned long *esp); -void show_stack(unsigned long *esp); +void show_stack(struct cpu_user_regs *regs); void show_registers(struct cpu_user_regs *regs); void show_page_walk(unsigned long addr); asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs); diff --git a/xen/include/asm-x86/x86_32/asm_defns.h b/xen/include/asm-x86/x86_32/asm_defns.h index d0243d4a52..c3772c6b1c 100644 --- a/xen/include/asm-x86/x86_32/asm_defns.h +++ b/xen/include/asm-x86/x86_32/asm_defns.h @@ -1,10 +1,20 @@ #ifndef __X86_32_ASM_DEFNS_H__ #define __X86_32_ASM_DEFNS_H__ +#ifndef NDEBUG +/* Indicate special exception stack frame by inverting the frame pointer. */ +#define SETUP_EXCEPTION_FRAME_POINTER \ + movl %esp,%ebp; \ + notl %ebp +#else +#define SETUP_EXCEPTION_FRAME_POINTER +#endif + #define __SAVE_ALL_PRE \ cld; \ pushl %eax; \ pushl %ebp; \ + SETUP_EXCEPTION_FRAME_POINTER; \ pushl %edi; \ pushl %esi; \ pushl %edx; \ diff --git a/xen/include/asm-x86/x86_64/asm_defns.h b/xen/include/asm-x86/x86_64/asm_defns.h index ff1d4927e0..d11af7228a 100644 --- a/xen/include/asm-x86/x86_64/asm_defns.h +++ b/xen/include/asm-x86/x86_64/asm_defns.h @@ -1,6 +1,15 @@ #ifndef __X86_64_ASM_DEFNS_H__ #define __X86_64_ASM_DEFNS_H__ +#ifndef NDEBUG +/* Indicate special exception stack frame by inverting the frame pointer. */ +#define SETUP_EXCEPTION_FRAME_POINTER \ + movq %rsp,%rbp; \ + notq %rbp +#else +#define SETUP_EXCEPTION_FRAME_POINTER +#endif + #define SAVE_ALL \ cld; \ pushq %rdi; \ @@ -14,6 +23,7 @@ pushq %r11; \ pushq %rbx; \ pushq %rbp; \ + SETUP_EXCEPTION_FRAME_POINTER; \ pushq %r12; \ pushq %r13; \ pushq %r14; \ -- 2.30.2